package com.atguigu.gmall.product.controller;

import io.swagger.annotations.Api;
import org.apache.commons.lang.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Api(tags = "测试接口")
@RestController
@RequestMapping("admin/product/test")
public class TestController {


    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;


//    @GetMapping("testLock")
//    public  void testLock() {
//
//        /**
//         * 使用分布式锁解决并发问题
//         */
////        给他加一把锁，使用的是setnx，无原子性
//        Boolean falg = redisTemplate.opsForValue().setIfAbsent("lock", "Ok");
//
////        使用setex设置过期时间
////        优化，防止误删其他线程的锁，加UUID唯一
//        String uuid = UUID.randomUUID().toString();
//        Boolean falg =   redisTemplate.opsForValue().setIfAbsent("lock",uuid,3, TimeUnit.SECONDS);
//
////        如果拿到锁
//        if (falg){
//            String num = redisTemplate.opsForValue().get("num");
//            if (StringUtils.isEmpty(num)) {
//                return;
//            } else {
//
//                int count = Integer.parseInt(num);
//
//                redisTemplate.opsForValue().set("num", String.valueOf(++count));
//
////                删除锁
////                if (redisTemplate.opsForValue().get("uuid").equals(uuid)){
////                    redisTemplate.delete("lock");
////                }
//
////                保证原子的一致性
//                //  定义一个lua 脚本
//                String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
//                //  准备执行lua 脚本
//                DefaultRedisScript<Long> redisScript = new DefaultRedisScript();
//                //  设置DefaultRedisScript 这个对象的泛型
//                redisScript.setResultType(Long.class);
//                //  将lua脚本放入DefaultRedisScript 对象中
//                redisScript.setScriptText(script);
//                redisTemplate.execute(redisScript, Arrays.asList("lock"),uuid);
//            }
//        }else {
////            没有拿到锁，等待一会，在尝试，自旋
//
//            try {
//                Thread.sleep(500);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            testLock();
//        }
//    }

    @GetMapping("testLock")
    public  void testLock() throws InterruptedException {



//        使用分布式锁redission解决并发问题
        RLock lock = redissonClient.getLock("lock");
//        上锁,10秒过期时间
//        lock.lock(10,TimeUnit.SECONDS);
//        boolean flag = lock.tryLock(1000, 10, TimeUnit.SECONDS);
//        if (flag){
//        异步锁
        lock.lockAsync();
            try {
                String num = redisTemplate.opsForValue().get("num");
                if (StringUtils.isEmpty(num)) {
                    return;
                } else {
                    int count = Integer.parseInt(num);
                    redisTemplate.opsForValue().set("num", String.valueOf(++count));
                }
            } finally {
                //        解锁
                lock.unlockAsync();
            }
//        }
    }
}
